#pragma once

#include "NvInferPlugin.h"
#include "cuda_runtime_api.h"

#include "../byte_tracker/object_detect_info.h"
#include "pose_util.h"
#include "../trt_infer.h"

#include <rclcpp/rclcpp.hpp>

#include <mutex>

namespace perception::camera {


class PoseDetectorIhs {
public:
    bool init(const std::string& engine_file_path);
    void deinit();
    int process(cv::Mat image, std::vector<perception::camera::ObjectDetectInfoPtr>& objs);
    void make_pipe(bool warmup);
    void copy_from_mat(const cv::Mat& image);
    void infer();
    void postprocess(std::vector<perception::camera::ObjectDetectInfoPtr>& objs, float score_thres);
    void postprocess_cpu(std::vector<perception::camera::ObjectDetectInfoPtr>& objs, float score_thres);
    float iou(const float& xmin1, const float& ymin1, const float& xmax1, const float& ymax1,
        const float& xmin2, const float& ymin2, const float& xmax2, const float& ymax2);

    static std::shared_ptr<PoseDetectorIhs> get_detector(const std::string& engine_file_path);

    int num_bindings;
    int num_inputs = 0;
    int num_outputs = 0;
    long long time_total_ = 0;
    long long infer_count_ = 0;
    std::vector<Binding> input_bindings;
    std::vector<Binding> output_bindings;
    std::vector<void*> host_ptrs;
    std::vector<void*> device_ptrs;
    std::string cam_name_;

private:
    PoseDetectorIhs();
    std::mutex pipe_mutex_;
    cv::Mat image_resize_, image_orig_;
    // 推理 h 实际为384, engine内部做pad, postprocess 需要减去pad
    // 网络要求size 需要为24的整数倍
    int infer_h_ = 360; 
    int infer_w_ = 640;
    int pad_h_ = 12;
    int pad_w_ = 0;
    int iframe_ = 0;
    std::map<int, int> hw2air_;
    nvinfer1::ICudaEngine* engine_ = nullptr;
    nvinfer1::IRuntime* runtime_ = nullptr;
    nvinfer1::IExecutionContext* context_ = nullptr;
    cudaStream_t stream_ = nullptr;
    NvLogger logger_ { nvinfer1::ILogger::Severity::kERROR };
    float* data_;
    static std::shared_ptr<PoseDetectorIhs> detector_;

    rclcpp::Logger logger__;
};

}